home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / piggy.c < prev    next >
C/C++ Source or Header  |  1998-04-24  |  25KB  |  987 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/piggy.c,v $
  15.  * $Revision: 1.3 $
  16.  * $Author: tfrieden $
  17.  * $Date: 1998/04/24 14:30:51 $
  18.  * 
  19.  * Functions for managing the pig files.
  20.  * 
  21.  */
  22.  
  23.  
  24. #pragma off (unreferenced)
  25. static char rcsid[] = "$Id: piggy.c,v 1.3 1998/04/24 14:30:51 tfrieden Exp $";
  26. #pragma on (unreferenced)
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31. #include <string.h>
  32.  
  33. #include "types.h"
  34. #include "inferno.h"
  35. #include "gr.h"
  36. //#include "mem.h"
  37. #include "cflib.h"
  38. #include "mono.h"
  39. #include "error.h"
  40. #include "sounds.h"
  41. #include "bm.h"
  42. #include "hash.h"
  43. #include "args.h"
  44. #include "palette.h"
  45. #include "gamefont.h"
  46. #include "rle.h"
  47. #include "screens.h"
  48.  
  49. //#include "soscomp.h"
  50. //The above include is part of a commercial 
  51. //sound library, so it cannot be included in a public 
  52. //release of the source code. -KRB
  53. // #include "no_sos.h" //Added by KRB
  54.  
  55. #include "piggy.h"
  56. #include "texmerge.h"
  57. #include "paging.h"
  58. #include "game.h"
  59. #include "text.h"
  60. #include "cfile.h"
  61. #include "newmenu.h"
  62. #include "byteswap.h"
  63. #include "fileutil.h"
  64.  
  65. //#define NO_DUMP_SOUNDS    1       //if set, dump bitmaps but not sounds
  66.  
  67. ubyte *BitmapBits = NULL;
  68. ubyte *SoundBits = NULL;
  69.  
  70. extern int Inferno_verbose;
  71.  
  72. typedef struct BitmapFile   {
  73.     char            name[15];
  74. } BitmapFile;
  75.  
  76. typedef struct SoundFile    {
  77.     char            name[15];
  78. } SoundFile;
  79.  
  80. hashtable AllBitmapsNames;
  81. hashtable AllDigiSndNames;
  82.  
  83. int Num_bitmap_files = 0;
  84. int Num_sound_files = 0;
  85.  
  86. digi_sound GameSounds[MAX_SOUND_FILES];
  87. int SoundOffset[MAX_SOUND_FILES];
  88. grs_bitmap GameBitmaps[MAX_BITMAP_FILES];
  89.  
  90. int Num_bitmap_files_new = 0;
  91. int Num_sound_files_new = 0;
  92. static BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
  93. static SoundFile AllSounds[ MAX_SOUND_FILES ];
  94.  
  95. int piggy_low_memory = 0;
  96.  
  97. #define DBM_FLAG_LARGE  128     // Flags added onto the flags struct in b
  98. #define DBM_FLAG_ABM        64
  99.  
  100. int Piggy_bitmap_cache_size = 0;
  101. int Piggy_bitmap_cache_next = 0;
  102. ubyte * Piggy_bitmap_cache_data = NULL;
  103. static int GameBitmapOffset[MAX_BITMAP_FILES];
  104. static ubyte GameBitmapFlags[MAX_BITMAP_FILES];
  105. ushort GameBitmapXlat[MAX_BITMAP_FILES];
  106.  
  107. #define PIGGY_BUFFER_SIZE (2048*1024)
  108.  
  109. int piggy_page_flushed = 0;
  110.  
  111. typedef struct DiskBitmapHeader {
  112.     char name[8]        __attribute__ ((packed));
  113.     ubyte dflags        __attribute__ ((packed));
  114.     ubyte width     __attribute__ ((packed));
  115.     ubyte height        __attribute__ ((packed));
  116.     ubyte flags     __attribute__ ((packed));
  117.     ubyte avg_color     __attribute__ ((packed));
  118.     int offset      __attribute__ ((packed));
  119. } DiskBitmapHeader;
  120.  
  121. #define SIZEOF_DISKBITMAPHEADER 17
  122.  
  123. typedef struct DiskSoundHeader {
  124.     char name[8]        __attribute__ ((packed));
  125.     int length      __attribute__ ((packed));
  126.     int data_length     __attribute__ ((packed));
  127.     int offset      __attribute__ ((packed));
  128. } DiskSoundHeader;
  129.  
  130.  
  131.  
  132. ubyte BigPig = 0;
  133.  
  134.  
  135. //#define BUILD_PSX_DATA 1
  136.  
  137. #ifdef BUILD_PSX_DATA
  138. FILE * count_file = NULL;
  139.  
  140. int num_good=0,num_bad=0;
  141. int num_good64=0,num_bad64=0;
  142.  
  143. void close_count_file()
  144. {
  145.     if ( count_file )   {
  146.         fprintf( count_file,"Good = %d\n", num_good );
  147.         fprintf( count_file,"Bad = %d\n", num_bad );
  148.         fprintf( count_file,"64Good = %d\n", num_good64 );
  149.         fprintf( count_file,"64Bad = %d\n", num_bad64 );
  150.         fclose(count_file);
  151.         count_file=NULL;
  152.     }
  153. }
  154.  
  155. void count_colors( int bnum, grs_bitmap * bmp )
  156. {
  157.     int i,colors;
  158.     ushort n[256];
  159.  
  160.     quantize_colors( bnum, bmp );
  161.  
  162.     if ( count_file == NULL )   {
  163.         atexit( close_count_file );
  164.         count_file = fopen( "bitmap.cnt", "wt" );
  165.     }
  166.     for (i=0; i<256; i++ )
  167.         n[i] = 0;
  168.  
  169.     for (i=0; i<bmp->bm_w*bmp->bm_h; i++ )  {
  170.         n[bmp->bm_data[i]]++;
  171.     }
  172.  
  173.     colors = 0;
  174.     for (i=0; i<256; i++ )
  175.         if (n[i]) colors++;
  176.  
  177.     if ( colors > 16 )  {
  178.         if ( (bmp->bm_w==64) && (bmp->bm_h==64) ) num_bad64++;
  179.         num_bad++;
  180.         fprintf( count_file, "Bmp has %d colors (%d x %d)\n", colors, bmp->bm_w, bmp->bm_h );
  181.     } else {
  182.         if ( (bmp->bm_w==64) && (bmp->bm_h==64) ) num_good64++;
  183.         num_good++;
  184.     }
  185. }
  186. #endif
  187.  
  188. void piggy_get_bitmap_name( int i, char * name )
  189. {
  190.     strncpy( name, AllBitmaps[i].name, 12 );
  191.     name[12] = 0;
  192. }
  193.  
  194. bitmap_index piggy_register_bitmap( grs_bitmap * bmp, char * name, int in_file )
  195. {
  196.     bitmap_index temp;
  197.     Assert( Num_bitmap_files < MAX_BITMAP_FILES );
  198.  
  199.     temp.index = Num_bitmap_files;
  200.  
  201.     if (!in_file)   {
  202.         if ( !BigPig )  gr_bitmap_rle_compress( bmp );
  203.         Num_bitmap_files_new++;
  204.     }
  205.  
  206.     strncpy( AllBitmaps[Num_bitmap_files].name, name, 12 );
  207.     hashtable_insert( &AllBitmapsNames, AllBitmaps[Num_bitmap_files].name, Num_bitmap_files );
  208.     GameBitmaps[Num_bitmap_files] = *bmp;
  209.     if ( !in_file ) {
  210.         GameBitmapOffset[Num_bitmap_files] = 0;
  211.         GameBitmapFlags[Num_bitmap_files] = bmp->bm_flags;
  212.     }
  213.     Num_bitmap_files++;
  214.  
  215.     return temp;
  216. }
  217.  
  218. int piggy_register_sound( digi_sound * snd, char * name, int in_file )
  219. {
  220.     int i;
  221.  
  222.     Assert( Num_sound_files < MAX_SOUND_FILES );
  223.  
  224.     strncpy( AllSounds[Num_sound_files].name, name, 12 );
  225.     hashtable_insert( &AllDigiSndNames, AllSounds[Num_sound_files].name, Num_sound_files );
  226.     GameSounds[Num_sound_files] = *snd;
  227.     if ( !in_file ) {
  228.         SoundOffset[Num_sound_files] = 0;   
  229.     }
  230.  
  231.     i = Num_sound_files;
  232.    
  233.     if (!in_file)
  234.         Num_sound_files_new++;
  235.  
  236.     Num_sound_files++;
  237.     return i;
  238. }
  239.  
  240. bitmap_index piggy_find_bitmap( char * name )   
  241. {
  242.     bitmap_index bmp;
  243.     int i;
  244.  
  245.     bmp.index = 0;
  246.  
  247.     i = hashtable_search( &AllBitmapsNames, name );
  248.     Assert( i != 0 );
  249.     if ( i < 0 )
  250.         return bmp;
  251.  
  252.     bmp.index = i;
  253.     return bmp;
  254. }
  255.  
  256. int piggy_find_sound( char * name ) 
  257. {
  258.     int i;
  259.  
  260.     i = hashtable_search( &AllDigiSndNames, name );
  261.  
  262.     if ( i < 0 )
  263.         return 255;
  264.  
  265.     return i;
  266. }
  267.  
  268. CFILE * Piggy_fp = NULL;
  269.  
  270. void piggy_close_file()
  271. {
  272.     if ( Piggy_fp ) {
  273.         cfclose( Piggy_fp );
  274.         Piggy_fp    = NULL;
  275.     }
  276. }
  277.  
  278. ubyte bogus_data[64*64];
  279. grs_bitmap bogus_bitmap;
  280. ubyte bogus_bitmap_initialized=0;
  281. digi_sound bogus_sound;
  282.  
  283. extern void bm_read_all(CFILE * fp);
  284.  
  285. int piggy_init()
  286. {
  287.     int sbytes = 0;
  288.     char temp_name_read[16];
  289.     char temp_name[16];
  290.     grs_bitmap temp_bitmap;
  291.     digi_sound temp_sound;
  292.     DiskBitmapHeader bmh;
  293.     DiskSoundHeader sndh;
  294.     int header_size, N_bitmaps, N_sounds;
  295.     int i,size, length, x, y;
  296.     char * filename;
  297.     int read_sounds = 1;
  298.     int Pigdata_start;
  299.  
  300.  
  301.     hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES );
  302.     hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES );
  303.  
  304.     if ( FindArg( "-nosound" ) || (digi_driver_board<1) )       {
  305.         read_sounds = 0;
  306.         mprintf(( 0, "Not loading sound data!!!!!\n" ));
  307.     }
  308.     
  309.     for (i=0; i<MAX_SOUND_FILES; i++ )  {
  310.         GameSounds[i].length = 0;
  311.         GameSounds[i].data = NULL;
  312.         SoundOffset[i] = 0;
  313.     }
  314.  
  315.     for (i=0; i<MAX_BITMAP_FILES; i++ )     {
  316.         GameBitmapXlat[i] = i;
  317.         GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
  318.     }
  319.  
  320.     if ( !bogus_bitmap_initialized )    {
  321.         int i;
  322.         ubyte c;
  323.         bogus_bitmap_initialized = 1;
  324.         memset( &bogus_bitmap, 0, sizeof(grs_bitmap) );
  325.         bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64;
  326.         bogus_bitmap.bm_data = bogus_data;
  327.         c = gr_find_closest_color( 0, 0, 63 );
  328.         for (i=0; i<4096; i++ ) bogus_data[i] = c;
  329.         c = gr_find_closest_color( 63, 0, 0 );
  330.         // Make a big red X !
  331.         for (i=0; i<64; i++ )   {
  332.             bogus_data[i*64+i] = c;
  333.             bogus_data[i*64+(63-i)] = c;
  334.         }
  335.         piggy_register_bitmap( &bogus_bitmap, "bogus", 1 );
  336.         bogus_sound.length = 64*64;
  337.         bogus_sound.data = bogus_data;
  338.         GameBitmapOffset[0] = 0;
  339.     }
  340.  
  341.     filename = "descent.pig";
  342.     
  343.     if ( FindArg( "-bigpig" ))
  344.         BigPig = 1;
  345.  
  346.     if ( FindArg( "-lowmem" ))
  347.         piggy_low_memory = 1;
  348.  
  349.     if ( FindArg( "-nolowmem" ))
  350.         piggy_low_memory = 0;
  351.  
  352.     if (piggy_low_memory)
  353.         digi_lomem = 1;
  354.  
  355.     if ( (i=FindArg( "-piggy" )) )  {
  356.         filename    = Args[i+1];
  357.         mprintf( (0, "Using alternate pigfile, '%s'\n", filename ));
  358.     }
  359.     Piggy_fp = cfopen( filename, "rb" );
  360.     if (Piggy_fp==NULL) return 0;
  361.  
  362.     cfread( &Pigdata_start, sizeof(int), 1, Piggy_fp );
  363.     Pigdata_start = swapint(Pigdata_start);
  364. #ifdef EDITOR
  365.     if ( FindArg("-nobm") )
  366. #endif
  367.     {
  368.         int j;
  369.         bm_read_all( Piggy_fp );    // Note connection to above if!!!
  370.         cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, Piggy_fp );
  371.         //GameBitmapXlat = swapshort(GameBitmapXlat);
  372.         for (j=0; j < MAX_BITMAP_FILES; j++) {
  373.             GameBitmapXlat[j] = swapshort(GameBitmapXlat[j]);
  374.         }
  375.     }
  376.  
  377.     cfseek( Piggy_fp, Pigdata_start, SEEK_SET );
  378.     size = cfilelength(Piggy_fp) - Pigdata_start;
  379.     length = size;
  380.     mprintf( (0, "\nReading data (%d KB) ", size/1024 ));
  381.  
  382.     cfread( &N_bitmaps, sizeof(int), 1, Piggy_fp );
  383.     N_bitmaps = swapint(N_bitmaps);
  384.     size -= sizeof(int);
  385.     cfread( &N_sounds, sizeof(int), 1, Piggy_fp );
  386.     N_sounds = swapint(N_sounds);
  387.     size -= sizeof(int);
  388.  
  389.     if (Inferno_verbose) {
  390.         printf("Number of bitmaps: %d\nNumber of sounds: %d\n", N_bitmaps, N_sounds);
  391.     }
  392.  
  393.     header_size = (N_bitmaps*SIZEOF_DISKBITMAPHEADER) + (N_sounds*sizeof(DiskSoundHeader));
  394.  
  395.     x = 60; y = 189;
  396.  
  397.     gr_set_curfont( Gamefonts[GFONT_SMALL] );   
  398.     gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 );
  399.     gr_printf( 0x8000, y-10, "%s...", TXT_LOADING_DATA );
  400.     gr_update(NULL);
  401.  
  402.  
  403.     for (i=0; i<N_bitmaps; i++ )    {
  404.         cfread( bmh.name, 8, 1, Piggy_fp );
  405.         bmh.dflags = read_byte(Piggy_fp);
  406.         bmh.width = read_byte(Piggy_fp);
  407.         bmh.height = read_byte(Piggy_fp);
  408.         bmh.flags = read_byte(Piggy_fp);
  409.         bmh.avg_color = read_byte(Piggy_fp);
  410.         bmh.offset = read_int_swap(Piggy_fp);
  411.  
  412.         //size -= sizeof(DiskBitmapHeader);
  413.         memcpy( temp_name_read, bmh.name, 8 );
  414.         temp_name_read[8] = 0;
  415.         if ( bmh.dflags & DBM_FLAG_ABM )    
  416.             sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 );
  417.         else
  418.             strcpy( temp_name, temp_name_read );
  419.         memset( &temp_bitmap, 0, sizeof(grs_bitmap) );
  420.         if ( bmh.dflags & DBM_FLAG_LARGE )
  421.             temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width+256;
  422.         else
  423.             temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width;
  424.         temp_bitmap.bm_h = bmh.height;
  425.         temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT;
  426.         temp_bitmap.avg_color = bmh.avg_color;
  427.         temp_bitmap.bm_data = Piggy_bitmap_cache_data;
  428.  
  429.         GameBitmapFlags[i+1] = 0;
  430.         if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT;
  431.         if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT;
  432.         if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING;
  433.         if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE;
  434.  
  435.         GameBitmapOffset[i+1] = bmh.offset + header_size + (sizeof(int)*2) + Pigdata_start;
  436.         Assert( (i+1) == Num_bitmap_files );
  437.         piggy_register_bitmap( &temp_bitmap, temp_name, 1 );
  438.     }
  439.  
  440.     for (i=0; i<N_sounds; i++ ) {
  441.         cfread( &sndh, sizeof(DiskSoundHeader), 1, Piggy_fp );
  442.         sndh.length = swapint(sndh.length);
  443.         sndh.data_length = swapint(sndh.data_length);
  444.         sndh.offset = swapint(sndh.offset);
  445.  
  446.         //size -= sizeof(DiskSoundHeader);
  447.         temp_sound.length = sndh.length;
  448.         temp_sound.data = (ubyte *)(sndh.offset + header_size + (sizeof(int)*2)+Pigdata_start);
  449.         SoundOffset[Num_sound_files] = sndh.offset + header_size + (sizeof(int)*2)+Pigdata_start;
  450.         memcpy( temp_name_read, sndh.name, 8 );
  451.         temp_name_read[8] = 0;
  452.         piggy_register_sound( &temp_sound, temp_name_read, 1 );
  453.         sbytes += sndh.length;
  454.         //mprintf(( 0, "%d bytes of sound\n", sbytes ));
  455.     }
  456.  
  457.     SoundBits = malloc( sbytes + 16 );
  458.     if ( SoundBits == NULL )
  459.         Error( "Not enough memory to load descent.pig sounds\n" );
  460.  
  461. #ifdef EDITOR
  462.     Piggy_bitmap_cache_size = size - header_size - sbytes + 16;
  463.     Assert( Piggy_bitmap_cache_size > 0 );
  464. #else
  465.     Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE;
  466. #endif
  467.     BitmapBits = malloc( Piggy_bitmap_cache_size );
  468.     if ( BitmapBits == NULL )
  469.         Error( "Not enough memory to load descent.pig bitmaps\n" );
  470.     Piggy_bitmap_cache_data = BitmapBits;   
  471.     Piggy_bitmap_cache_next = 0;
  472.     
  473.     mprintf(( 0, "\nBitmaps: %d KB   Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 ));
  474.  
  475.     atexit(piggy_close_file);
  476.  
  477. //  mprintf( (0, "<<<<Paging in all piggy bitmaps...>>>>>" ));
  478. //  for (i=0; i < Num_bitmap_files; i++ )   {
  479. //      bitmap_index bi;
  480. //      bi.index = i;
  481. //      PIGGY_PAGE_IN( bi );
  482. //  }
  483. //  mprintf( (0, "\n (USed %d / %d KB)\n", Piggy_bitmap_cache_next/1024, (size - header_size - sbytes + 16)/1024 ));
  484. //  key_getch();
  485.  
  486.  
  487.     return 0;
  488. }
  489.  
  490. int piggy_is_needed(int soundnum)
  491. {
  492.     int i;
  493.  
  494.     if ( !digi_lomem ) return 1;
  495.  
  496.     for (i=0; i<MAX_SOUNDS; i++ )   {
  497.         if ( (AltSounds[i] < 255) && (Sounds[AltSounds[i]] == soundnum) )
  498.             return 1;
  499.     }
  500.     return 0;
  501. }
  502.  
  503. void piggy_read_sounds()
  504. {
  505.     ubyte * ptr;
  506.     int i, sbytes;
  507.  
  508.     ptr = SoundBits;
  509.     sbytes = 0;
  510.  
  511.     for (i=0; i<Num_sound_files; i++ )  {
  512.         digi_sound *snd = &GameSounds[i];
  513.  
  514.         if ( SoundOffset[i] > 0 )   {
  515.             if ( piggy_is_needed(i) )   {
  516.                 cfseek( Piggy_fp, SoundOffset[i], SEEK_SET );
  517.     
  518.                 // Read in the sound data!!!
  519.                 snd->data = ptr;
  520.                 ptr += snd->length;
  521.                 sbytes += snd->length;
  522.                 cfread( snd->data, snd->length, 1, Piggy_fp );
  523.             }
  524.         }
  525.     }
  526.  
  527.     mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 ));
  528.  
  529. }
  530.  
  531. extern int descent_critical_error;
  532. extern unsigned descent_critical_deverror;
  533. extern unsigned descent_critical_errcode;
  534.  
  535. char * crit_errors[13] = { "Write Protected", "Unknown Unit", "Drive Not Ready", "Unknown Command", "CRC Error", \
  536. "Bad struct length", "Seek Error", "Unknown media type", "Sector not found", "Printer out of paper", "Write Fault", \
  537. "Read fault", "General Failure" };
  538.  
  539. void piggy_critical_error()
  540. {
  541.     grs_canvas * save_canv;
  542.     grs_font * save_font;
  543.     int i;
  544.     save_canv = grd_curcanv;
  545.     save_font = grd_curcanv->cv_font;
  546.     gr_palette_load( gr_palette );
  547.     i = nm_messagebox( "Disk Error", 2, "Retry", "Exit", "%s\non drive %c:", crit_errors[descent_critical_errcode&0xf], (descent_critical_deverror&0xf)+'A'  );
  548.     if ( i == 1 )
  549.         exit(1);
  550.     gr_set_current_canvas(save_canv);
  551.     grd_curcanv->cv_font = save_font;
  552. }
  553.  
  554. void piggy_bitmap_page_in( bitmap_index bitmap )
  555. {
  556.     grs_bitmap * bmp;
  557.     int i,org_i,temp;
  558.  
  559.     i = bitmap.index;
  560.     Assert( i >= 0 );
  561.     Assert( i < MAX_BITMAP_FILES );
  562.     Assert( i < Num_bitmap_files );
  563.     Assert( Piggy_bitmap_cache_size > 0 );
  564.  
  565.     if ( i < 1 ) return;
  566.     if ( i >= MAX_BITMAP_FILES ) return;
  567.     if ( i >= Num_bitmap_files ) return;
  568.  
  569.     if ( GameBitmapOffset[i] == 0 ) return;     // A read-from-disk bitmap!!!
  570.  
  571.     if ( piggy_low_memory ) {
  572.         org_i = i;
  573.         i = GameBitmapXlat[i];      // Xlat for low-memory settings!
  574.     }
  575.     bmp = &GameBitmaps[i];
  576.     
  577.     if ( bmp->bm_flags & BM_FLAG_PAGED_OUT )    {
  578.         stop_time();
  579.  
  580.     ReDoIt:
  581.         descent_critical_error = 0;
  582.         cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET );
  583.         if ( descent_critical_error )   {
  584.             piggy_critical_error();
  585.             goto ReDoIt;
  586.         }
  587.         bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next];
  588.         bmp->bm_flags = GameBitmapFlags[i];
  589.     
  590.         if ( bmp->bm_flags & BM_FLAG_RLE )  {
  591.             int zsize = 0;
  592.             descent_critical_error = 0;
  593.             //temp = cfread( &zsize, 1, sizeof(int), Piggy_fp );
  594.             //zsize = swapint(zsize);
  595.             zsize = read_int_swap(Piggy_fp);
  596.             if ( descent_critical_error )   {
  597.                 piggy_critical_error();
  598.                 goto ReDoIt;
  599.             }
  600.     
  601.             // GET JOHN NOW IF YOU GET THIS ASSERT!!!
  602.             Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );  
  603.             if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) {
  604.                 piggy_bitmap_page_out_all();
  605.                 goto ReDoIt;
  606.             }
  607.             // WHAT THE HELL IS THIS???
  608.             memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) );
  609.             Piggy_bitmap_cache_next += sizeof(int);
  610.             descent_critical_error = 0;
  611.             temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp );
  612.             if ( descent_critical_error )   {
  613.                 piggy_critical_error();
  614.                 goto ReDoIt;
  615.             }
  616.             Piggy_bitmap_cache_next += zsize-4;
  617.         } else {
  618.             // GET JOHN NOW IF YOU GET THIS ASSERT!!!
  619.             Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size );  
  620.             if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) {
  621.                 piggy_bitmap_page_out_all();
  622.                 goto ReDoIt;
  623.             }
  624.             descent_critical_error = 0;
  625.             temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp );
  626.             if ( descent_critical_error )   {
  627.                 piggy_critical_error();
  628.                 goto ReDoIt;
  629.             }
  630.             Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w;
  631.  
  632.         }
  633.         start_time();
  634.     }
  635.  
  636.     if ( piggy_low_memory ) {
  637.         if ( org_i != i )
  638.             GameBitmaps[org_i] = GameBitmaps[i];
  639.     }
  640. }
  641.  
  642. void piggy_bitmap_page_out_all()
  643. {
  644.     int i;
  645.     
  646.     Piggy_bitmap_cache_next = 0;
  647.  
  648.     piggy_page_flushed++;
  649.  
  650.     texmerge_flush();
  651.     rle_cache_flush();
  652.  
  653.     for (i=0; i<Num_bitmap_files; i++ )     {
  654.         if ( GameBitmapOffset[i] > 0 )  {   // Don't page out bitmaps read from disk!!!
  655.             GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT;
  656.             GameBitmaps[i].bm_data = Piggy_bitmap_cache_data;
  657.         }
  658.     }
  659.  
  660.     mprintf(( 0, "Flushing piggy bitmap cache\n" ));
  661. }
  662.  
  663. void piggy_load_level_data()
  664. {
  665.     piggy_bitmap_page_out_all();
  666.     paging_touch_all();
  667. }
  668.  
  669. #ifdef EDITOR
  670. void piggy_dump_all()
  671. {
  672.     int i, xlat_offset;
  673.     FILE * fp;
  674. #ifndef RELEASE
  675.     FILE * fp1;
  676.     FILE * fp2;
  677. #endif
  678.     char * filename;
  679.     int data_offset;
  680.     int org_offset;
  681.     DiskBitmapHeader bmh;
  682.     DiskSoundHeader sndh;
  683.     int header_offset;
  684.     char subst_name[32];
  685.  
  686.     #ifdef NO_DUMP_SOUNDS
  687.     Num_sound_files = 0;
  688.     Num_sound_files_new = 0;
  689.     #endif
  690.  
  691. //  {
  692. //  bitmap_index bi;
  693. //  bi.index = 614;
  694. //  PIGGY_PAGE_IN( bi );
  695. //  count_colors( bi.index, &GameBitmaps[bi.index] );
  696. //  key_getch();
  697. //  }
  698. //  {
  699. //  bitmap_index bi;
  700. //  bi.index = 478;
  701. //  PIGGY_PAGE_IN( bi );
  702. //  Int3();
  703. //  count_colors( bi.index, &GameBitmaps[bi.index] );
  704. //  key_getch();
  705. //  }
  706. //  {
  707. //  bitmap_index bi;
  708. //  bi.index = 1398;
  709. //  PIGGY_PAGE_IN( bi );
  710. //  count_colors( bi.index, &GameBitmaps[bi.index] );
  711. //  key_getch();
  712. //  }
  713. //  {
  714. //  bitmap_index bi;
  715. //  bi.index = 642;
  716. //  PIGGY_PAGE_IN( bi );
  717. //  count_colors( bi.index, &GameBitmaps[bi.index] );
  718. //  key_getch();
  719. //  }
  720. //  {
  721. //  bitmap_index bi;
  722. //  bi.index = 529;
  723. //  PIGGY_PAGE_IN( bi );
  724. //  count_colors( bi.index, &GameBitmaps[bi.index] );
  725. //  key_getch();
  726. //  }
  727. //  exit(0);
  728. //
  729.     if ((Num_bitmap_files_new == 0) && (Num_sound_files_new == 0) )
  730.         return;
  731.  
  732.     mprintf( (0, "Paging in all piggy bitmaps..." ));
  733.     for (i=0; i < Num_bitmap_files; i++ )   {
  734.         bitmap_index bi;
  735.         bi.index = i;
  736.         PIGGY_PAGE_IN( bi );
  737.     }
  738.     mprintf( (0, "\n" ));
  739.  
  740.     piggy_close_file();
  741.  
  742.     mprintf( (0, "Creating descent.pig..." ));
  743.     filename = "descent.pig";
  744.     if ( (i=FindArg( "-piggy" )) )  {
  745.         filename    = Args[i+1];
  746.         mprintf( (0, "Dumping alternate pigfile, '%s'\n", filename ));
  747.     } 
  748.     mprintf( (0, "\nDumping bitmaps..." ));
  749.  
  750.     fp = fopen( filename, "wb" );
  751.     Assert( fp!=NULL );
  752.  
  753. #ifndef RELEASE
  754.     fp1 = fopen( "piggy.lst", "wt" );
  755.     fp2 = fopen( "piggy.all", "wt" );
  756. #endif
  757.  
  758.     i = 0;
  759.     fwrite( &i, sizeof(int), 1, fp );   
  760.     bm_write_all(fp);
  761.     xlat_offset = ftell(fp);
  762.     fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, fp );
  763.     i = ftell(fp);
  764.     fseek( fp, 0, SEEK_SET );
  765.     fwrite( &i, sizeof(int), 1, fp );
  766.     fseek( fp, i, SEEK_SET );
  767.         
  768.     Num_bitmap_files--;
  769.     fwrite( &Num_bitmap_files, sizeof(int), 1, fp );
  770.     Num_bitmap_files++;
  771.     fwrite( &Num_sound_files, sizeof(int), 1, fp );
  772.  
  773.     header_offset = ftell(fp);
  774.     header_offset += ((Num_bitmap_files-1)*SIZEOF_DISKBITMAPHEADER) + (Num_sound_files*sizeof(DiskSoundHeader));
  775.     data_offset = header_offset;
  776.  
  777.     for (i=1; i < Num_bitmap_files; i++ )   {
  778.         int *size;
  779.         grs_bitmap *bmp;
  780.  
  781.         {       
  782.             char * p, *p1;
  783.             p = strchr(AllBitmaps[i].name,'#');
  784.             if (p)  {
  785.                 int n;
  786.                 p1 = p; p1++; 
  787.                 n = atoi(p1);
  788.                 *p = 0;
  789. #ifndef RELEASE
  790.                 if (n==0)   {       
  791.                     fprintf( fp2, "%s.abm\n", AllBitmaps[i].name );
  792.                 }   
  793. #endif
  794.                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
  795.                 Assert( n <= 63 );
  796.                 bmh.dflags = DBM_FLAG_ABM + n;
  797.                 *p = '#';
  798.             }else {
  799. #ifndef RELEASE
  800.                 fprintf( fp2, "%s.bbm\n", AllBitmaps[i].name );
  801. #endif
  802.                 memcpy( bmh.name, AllBitmaps[i].name, 8 );
  803.                 bmh.dflags = 0;
  804.             }
  805.         }
  806.         bmp = &GameBitmaps[i];
  807.  
  808.         Assert( !(bmp->bm_flags&BM_FLAG_PAGED_OUT) );
  809.  
  810. #ifndef RELEASE
  811.         fprintf( fp1, "BMP: %s, size %d bytes", AllBitmaps[i].name, bmp->bm_rowsize * bmp->bm_h );
  812. #endif
  813.         org_offset = ftell(fp);
  814.         bmh.offset = data_offset - header_offset;
  815.         fseek( fp, data_offset, SEEK_SET );
  816.  
  817.         if ( bmp->bm_flags & BM_FLAG_RLE )  {
  818.             size = (int *)bmp->bm_data;
  819.             fwrite( bmp->bm_data, sizeof(ubyte), *size, fp );
  820.             data_offset += *size;
  821.             //bmh.data_length = *size;
  822. #ifndef RELEASE
  823.             fprintf( fp1, ", and is already compressed to %d bytes.\n", *size );
  824. #endif
  825.         } else {
  826.             fwrite( bmp->bm_data, sizeof(ubyte), bmp->bm_rowsize * bmp->bm_h, fp );
  827.             data_offset += bmp->bm_rowsize * bmp->bm_h;
  828.             //bmh.data_length = bmp->bm_rowsize * bmp->bm_h;
  829. #ifndef RELEASE
  830.             fprintf( fp1, ".\n" );
  831. #endif
  832.         }
  833.         fseek( fp, org_offset, SEEK_SET );
  834.         if ( GameBitmaps[i].bm_w > 255 )    {
  835.             Assert( GameBitmaps[i].bm_w < 512 );
  836.             bmh.width = GameBitmaps[i].bm_w - 256;
  837.             bmh.dflags |= DBM_FLAG_LARGE;
  838.         } else {
  839.             bmh.width = GameBitmaps[i].bm_w;
  840.         }
  841.         Assert( GameBitmaps[i].bm_h < 256 );
  842.         bmh.height = GameBitmaps[i].bm_h;
  843.         bmh.flags = GameBitmaps[i].bm_flags;
  844.         if (piggy_is_substitutable_bitmap( AllBitmaps[i].name, subst_name ))    {
  845.             bitmap_index other_bitmap;
  846.             other_bitmap = piggy_find_bitmap( subst_name );
  847.             GameBitmapXlat[i] = other_bitmap.index;
  848.             bmh.flags |= BM_FLAG_PAGED_OUT;
  849.             //mprintf(( 0, "Skipping bitmap %d\n", i ));
  850.             //mprintf(( 0, "Marking '%s' as substitutible\n", AllBitmaps[i].name ));
  851.         } else  {
  852. #ifdef BUILD_PSX_DATA
  853.             count_colors( i, &GameBitmaps[i] );
  854. #endif
  855.             bmh.flags &= ~BM_FLAG_PAGED_OUT;
  856.         }
  857.         bmh.avg_color=GameBitmaps[i].avg_color;
  858.         fwrite( &bmh, SIZEOF_DISKBITMAPHEADER, 1, fp );            // Mark as a bitmap
  859.     }
  860.  
  861.     mprintf( (0, "\nDumping sounds..." ));
  862.  
  863.     for (i=0; i < Num_sound_files; i++ )    {
  864.         digi_sound *snd;
  865.  
  866.         snd = &GameSounds[i];
  867.         strcpy( sndh.name, AllSounds[i].name );
  868.         sndh.length = GameSounds[i].length;
  869.         sndh.offset = data_offset - header_offset;
  870.  
  871.         org_offset = ftell(fp);
  872.         fseek( fp, data_offset, SEEK_SET );
  873.  
  874.         sndh.data_length = GameSounds[i].length;
  875.         fwrite( snd->data, sizeof(ubyte), snd->length, fp );
  876.         data_offset += snd->length;
  877.         fseek( fp, org_offset, SEEK_SET );
  878.         fwrite( &sndh, sizeof(DiskSoundHeader), 1, fp );            // Mark as a bitmap
  879.  
  880. #ifndef RELEASE
  881.         fprintf( fp1, "SND: %s, size %d bytes\n", AllSounds[i].name, snd->length );
  882.  
  883.         fprintf( fp2, "%s.raw\n", AllSounds[i].name );
  884. #endif
  885.     }
  886.  
  887.     fseek( fp, xlat_offset, SEEK_SET );
  888.     fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, fp );
  889.  
  890.     fclose(fp);
  891.  
  892.     mprintf( (0, "\n" ));
  893.  
  894.     mprintf( (0, " Dumped %d assorted bitmaps.\n", Num_bitmap_files ));
  895.     mprintf( (0, " Dumped %d assorted sounds.\n", Num_sound_files ));
  896.  
  897. #ifndef RELEASE
  898.     fprintf( fp1, " Dumped %d assorted bitmaps.\n", Num_bitmap_files );
  899.     fprintf( fp1, " Dumped %d assorted sounds.\n", Num_sound_files );
  900.  
  901.     fclose(fp1);
  902.     fclose(fp2);
  903. #endif
  904.  
  905. #ifdef BUILD_PSX_DATA
  906.     fp = fopen( "psx/descent.dat", "wb" );
  907.     fwrite( &i, sizeof(int), 1, fp );   
  908.     bm_write_all(fp);
  909.     fwrite( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, fp );
  910.     fclose(fp);
  911. #endif
  912.  
  913.     // Never allow the game to run after building pig.
  914.     exit(0);
  915. }
  916.  
  917. #endif
  918.  
  919. void piggy_close()
  920. {
  921.  
  922.  
  923.     if (BitmapBits)
  924.         free(BitmapBits);
  925.  
  926.     if ( SoundBits )
  927.         free( SoundBits );
  928.  
  929.     hashtable_free( &AllBitmapsNames );
  930.     hashtable_free( &AllDigiSndNames );
  931.  
  932.  
  933. }
  934.  
  935. int piggy_does_bitmap_exist_slow( char * name )
  936. {
  937.     int i;
  938.  
  939.     for (i=0; i<Num_bitmap_files; i++ ) {
  940.         if ( !strcmp( AllBitmaps[i].name, name) )
  941.             return 1;
  942.     }
  943.     return 0;
  944. }
  945.  
  946.  
  947. #define NUM_GAUGE_BITMAPS 10
  948. char * gauge_bitmap_names[NUM_GAUGE_BITMAPS] = { "gauge01", "gauge02", "gauge06", "targ01", "targ02", "targ03", "targ04", "targ05", "targ06", "gauge18" };
  949.  
  950. int piggy_is_gauge_bitmap( char * base_name )
  951. {
  952.     int i;
  953.     for (i=0; i<NUM_GAUGE_BITMAPS; i++ )    {
  954.         if ( !stricmp( base_name, gauge_bitmap_names[i] ))  
  955.             return 1;
  956.     }
  957.  
  958.     return 0;   
  959. }
  960.  
  961. int piggy_is_substitutable_bitmap( char * name, char * subst_name )
  962. {
  963.     int frame;
  964.     char * p;
  965.     char base_name[ 16 ];
  966.     
  967.     strcpy( subst_name, name );
  968.     p = strchr( subst_name, '#' );
  969.     if ( p )    {
  970.         frame = atoi( &p[1] );
  971.         *p = 0;
  972.         strcpy( base_name, subst_name );
  973.         if ( !piggy_is_gauge_bitmap( base_name ))   {
  974.             sprintf( subst_name, "%s#%d", base_name, frame+1 );
  975.             if ( piggy_does_bitmap_exist_slow( subst_name )  )  {
  976.                 if ( frame & 1 ) {
  977.                     sprintf( subst_name, "%s#%d", base_name, frame-1 );
  978.                     return 1;
  979.                 }
  980.             }
  981.         }
  982.     }
  983.     strcpy( subst_name, name );
  984.     return 0;
  985. }
  986.  
  987.